//SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package board_member_api_serv

import (
	"context"
	"time"

	"gitcode.com/eteam/api-server/api_common"
	"gitcode.com/eteam/api-server/dao"
	"gitcode.com/eteam/api-server/dao/board_dao"
	"gitcode.com/eteam/api-server/notice_serv"
	"gitcode.com/eteam/proto-gen-go.git/board_member_api"
	"gitcode.com/eteam/proto-gen-go.git/notices/notices_board"
	"github.com/dchest/uniuri"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *BoardMemberApiImpl) GenInvite(ctx context.Context, req *board_member_api.GenInviteRequest) (*board_member_api.GenInviteResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_member_api.GenInviteResponse{
			Code:   board_member_api.GenInviteResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_member_api.GenInviteResponse{
			Code:   board_member_api.GenInviteResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !memberItem.Admin {
		return &board_member_api.GenInviteResponse{
			Code:   board_member_api.GenInviteResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	inviteCode := ""
	for i := 0; i < 10; i++ {
		inviteCode = uniuri.NewLenChars(64, []byte("0123456789abcdefghijklmnopqrstvuwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"))
		exist, err := board_dao.InviteDao.Exist(ctx, inviteCode)
		if err != nil {
			return nil, err
		}
		if !exist {
			break
		}
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = board_dao.InviteDao.Insert(sessCtx, &board_dao.InviteInfoDbItem{
			InviteCode: inviteCode,
			BoardId:    req.BoardId,
			GenTime:    nowTime,
			ExpireTime: nowTime + int64(req.TtlHour)*3600*1000,
			TtlHour:    req.TtlHour,
		})
		if err != nil {
			return nil, err
		}
		return &board_member_api.GenInviteResponse{
			Code:       board_member_api.GenInviteResponse_CODE_OK,
			InviteCode: inviteCode,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*board_member_api.GenInviteResponse), nil
}

func (apiImpl *BoardMemberApiImpl) Join(ctx context.Context, req *board_member_api.JoinRequest) (*board_member_api.JoinResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_member_api.JoinResponse{
			Code:   board_member_api.JoinResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//获取邀请
	inviteItem, err := board_dao.InviteDao.Get(ctx, req.InviteCode)
	if err != nil {
		return &board_member_api.JoinResponse{
			Code:   board_member_api.JoinResponse_CODE_WRONG_INVITE_CODE,
			ErrMsg: "错误的邀请码",
		}, nil
	}
	nowTime := time.Now().UnixMilli()
	if inviteItem.ExpireTime < nowTime {
		return &board_member_api.JoinResponse{
			Code:   board_member_api.JoinResponse_CODE_WRONG_INVITE_CODE,
			ErrMsg: "邀请码已过期",
		}, nil
	}
	//检查是否存在成员
	exist, err := board_dao.MemberInfoDao.Exist(ctx, inviteItem.BoardId, sessItem.UserId)
	if err != nil {
		return nil, err
	}
	if exist {
		return &board_member_api.JoinResponse{
			Code:    board_member_api.JoinResponse_CODE_OK,
			BoardId: inviteItem.BoardId,
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = api_common.JoinBoard(sessCtx, &board_dao.MemberInfoDbItem{
			MemberUserId: sessItem.UserId,
			BoardId:      inviteItem.BoardId,
			LastViewTime: nowTime,
			CreateTime:   nowTime,
			Admin:        false,
		})
		if err != nil {
			return nil, err
		}
		return &board_member_api.JoinResponse{
			Code:    board_member_api.JoinResponse_CODE_OK,
			BoardId: inviteItem.BoardId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(inviteItem.BoardId, &notices_board.JoinBoardNotice{
		BoardId:      inviteItem.BoardId,
		MemberUserId: sessItem.UserId,
	})
	return ret.(*board_member_api.JoinResponse), nil
}
